package com.tangyh.basic.base;

import com.tangyh.basic.base.constant.StringPool;
import com.tangyh.basic.utils.CommonUtil;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;

import java.util.HashMap;
import java.util.Map;

/**
 * 接口调用返回结果
 *
 * @version V1.0
 * @author: Sidon
 * @createTime: 2021-06-03 16:41
 * Copyright (C)2021-2021 福建省金柠网络科技有限公司. All rights reserved.
 */
@Getter
@Setter
@SuppressWarnings("ALL")
public class AR<T> {

    /**
     * 自定义描述
     */
    private static final String DEF_ERROR_MESSAGE = "系统繁忙，请稍候再试";
    private static final String THROW_EXCEPTION_MESSAGE = "系统执行出现异常，请稍候再试";

    /**
     * 自定义状态码
     */
    private static final int SUCCESS_CODE = 0;
    private static final int FAIL_CODE = -1;
    private static final int THROW_EXCEPTION_CODE = -3;

    /**
     * 调用是否成功标识
     * <pre>
     *      0:成功
     *     -1:失败
     *     -2:超时
     *     -3:异常
     * </pre>
     */
    private int code;

    /**
     * 操作成功状态码，Http请求或自定义状态码
     */
    private String returnCode = StringPool.DEFAULT_PLACE_HOLDER;

    /**
     * 是否由异常导致的错误
     */
    private Boolean isException = false;

    /**
     * 操作成功或失败返回的数据
     */
    private T data;

    /**
     * 结果消息，如果调用成功，消息通常为空T
     */
    private String msg = "ok";
    /**
     * 出现异常时候返回的错误信息
     */
    private String errorMessage;

    /**
     * 附加数据
     */
    @ApiModelProperty(value = "附加数据")
    private Map<Object, Object> extra;

    /**
     * 响应时间
     */
    private long timestamp = System.currentTimeMillis();

    private AR() {
        this.timestamp = System.currentTimeMillis();
    }

    private AR(int code, String msg) {
        this.code = code;
        this.msg = msg;
        this.timestamp = System.currentTimeMillis();
    }

    private AR(int code, String msg, Boolean isException) {
        this(code, msg);
        this.isException = isException;
    }

    private AR(int code, String msg, Boolean isException, String errorMessage) {
        this(code, msg, isException);
        this.errorMessage = errorMessage;
    }

    private AR(int code, T data, String msg) {
        this.code = code;
        this.data = data;
        this.msg = msg;
        this.timestamp = System.currentTimeMillis();
    }

    private AR(int code, String msg, String returnCode) {
        this(code, msg);
        this.returnCode = returnCode;
    }

    private AR(int code, String msg, String returnCode, T data) {
        this(code, msg, returnCode);
        this.data = data;
    }

    private AR(int code, String msg, String returnCode, String errorMessage) {
        this(code, msg, returnCode);
        this.errorMessage = errorMessage;
    }

    private AR(int code, String msg, String returnCode, Boolean isException) {
        this(code, msg, returnCode);
        this.isException = isException;
    }


    /**
     * 操作成功
     *
     * @return 成功结果
     */
    public static <E> AR<E> success() {
        return new AR<>(SUCCESS_CODE, "ok");
    }

    /**
     * 操作成功
     *
     * @param data 操作成功返回的数据
     * @return 成功结果
     */
    public static <E> AR<E> success(E data) {
        return new AR<>(SUCCESS_CODE, data, "ok");
    }

    /**
     * 操作成功
     *
     * @param data 操作成功返回的数据
     * @param msg  操作成功返回的说明
     * @return 成功结果
     */
    public static <E> AR<E> success(E data, String msg) {
        return new AR<>(SUCCESS_CODE, data, msg);
    }

    /**
     * 操作成功
     *
     * @param data       操作成功返回的数据
     * @param msg        操作成功返回的说明
     * @param returnCode 操作成功状态码，Http请求或自定义状态码
     * @return 成功结果
     */
    public static <E> AR<E> success(E data, String msg, String returnCode) {
        return new AR<>(SUCCESS_CODE, msg, returnCode, data);
    }

    /**
     * 操作成功
     *
     * @param msg        操作成功返回的说明
     * @param returnCode 操作成功状态码，Http请求或自定义状态码
     * @return 成功结果
     */
    public static <E> AR<E> success(String msg, String returnCode) {
        return new AR<>(SUCCESS_CODE, msg, returnCode);
    }


    /**
     * 操作失败
     *
     * @return 失败结果
     */
    public static <E> AR<E> fail() {
        return fail("fail");
    }

    /**
     * 操作失败
     *
     * @param msg 操作失败返回的说明
     * @return 失败结果
     */
    public static <E> AR<E> fail(String msg) {
        return new AR<>(FAIL_CODE, msg);
    }

    /**
     * 操作失败
     *
     * @param returnCode 操作失败状态码，Http请求或自定义状态码
     * @param msg        操作失败返回的说明
     * @return 失败结果
     */
    public static <E> AR<E> fail(String returnCode, String msg) {
        return new AR<>(FAIL_CODE, CommonUtil.isEmpty(msg) ? DEF_ERROR_MESSAGE : msg, returnCode);
    }

    /**
     * 操作失败
     *
     * @param returnCode   操作失败状态码，Http请求或自定义状态码
     * @param msg          操作失败返回的说明
     * @param errorMessage 操作失败状态码，Http请求或自定义错误信息描述
     * @return 失败结果
     */
    public static <E> AR<E> fail(String returnCode, String msg, String errorMessage) {
        return new AR<>(FAIL_CODE, CommonUtil.isEmpty(msg) ? DEF_ERROR_MESSAGE : msg, returnCode, errorMessage);
    }

    /**
     * 操作失败
     *
     * @param returnCode  操作失败状态码，Http请求或自定义状态码
     * @param msg         操作失败返回的说明
     * @param isException 是否由于异常导致错误
     * @return 失败结果
     */
    public static <E> AR<E> fail(String returnCode, String msg, Boolean isException) {
        return new AR<>(FAIL_CODE, CommonUtil.isEmpty(msg) ? DEF_ERROR_MESSAGE : msg, returnCode, isException);
    }

    /**
     * 由于异常导致的错误，
     *
     * @param msg          自定义信息描述
     * @param errorMessage 异常信息
     * @return 错误结果，返回异常错误信息和自定义信息
     */
    public static <E> AR<E> error(String msg, String errorMessage) {
        return new AR<>(THROW_EXCEPTION_CODE, msg, true, errorMessage);
    }

    /**
     * 由于异常导致的错误
     *
     * @param msg 异常信息描述
     * @return 错误结果，返回异常错误信息和自定义信息
     */
    public static <E> AR<E> error(String msg) {
        return new AR<>(THROW_EXCEPTION_CODE, msg, true, msg);
    }

    /**
     * 由于异常导致的错误
     *
     * @param throwable 异常
     * @return 错误结果，返回异常错误信息
     */
    public static <E> AR<E> error(Throwable throwable) {
        String msg = throwable != null ? throwable.getMessage() : THROW_EXCEPTION_MESSAGE;
        return new AR<>(THROW_EXCEPTION_CODE, msg, true);
    }

    /**
     * 由于异常导致的错误，
     *
     * @param throwable 异常
     * @param msg       自定义信息描述
     * @return 错误结果，返回异常错误信息和自定义信息
     */
    public static <E> AR<E> error(Throwable throwable, String msg) {
        String errorMessage = throwable != null ? throwable.getMessage() : THROW_EXCEPTION_MESSAGE;
        return new AR<>(THROW_EXCEPTION_CODE, msg, true, errorMessage);
    }


    /**
     * 是否操作成功
     *
     * @return
     */
    public Boolean isSuccess() {
        return this.code == SUCCESS_CODE;
    }

    /**
     * 是否操作失败
     *
     * @return
     */
    public Boolean isFail() {
        return this.code == FAIL_CODE;
    }

    /**
     * 是否错误
     *
     * @return
     */
    public Boolean isError() {
        return this.code == THROW_EXCEPTION_CODE;
    }

    @Override
    public String toString() {
        return String.format("Code:%s, Data:%s ", code, data);
    }

    public AR<T> put(String key, Object value) {
        if (this.extra == null) {
            this.extra = new HashMap<>(16);
        }
        this.extra.put(key, value);
        return this;
    }

    public AR<T> putAll(Map<Object, Object> extra) {
        if (this.extra == null) {
            this.extra = new HashMap<>(16);
        }
        this.extra.putAll(extra);
        return this;
    }

    /**
     * 字节数据
     *
     * @param bytes
     * @return
     */
    public AR<T> setByteData(byte[] bytes) {
        this.put("byteData", bytes);
        return this;
    }

    /**
     * 获取字节数据
     *
     * @return
     */
    public byte[] getBytes() {
        return (byte[]) this.getExtra().get("byteData");
    }
}
